#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0800
#endif
#include "WOH_Input.h"
#include "WOH_GameTime.h"

CInput::CInput(void)
{
	m_pInput = NULL;
	m_pDevKeyBoard = NULL;
	m_pDevMouse = NULL;
	::ZeroMemory(m_keyState,sizeof(m_keyState));
	::ZeroMemory(m_nKeyStamp,sizeof(m_nKeyStamp));
	::ZeroMemory((void*)&m_mouseState,sizeof(m_mouseState));
	::ZeroMemory(m_nMouseStamp,sizeof(m_nMouseStamp));
}

CInput::~CInput(void)
{
}

CInput& CInput::GetInstance()
{
	static CInput input;
	return input;
}

bool CInput::Initialize( HWND hWnd ,HINSTANCE hInstance)
{
	m_hWnd = hWnd;
	m_hInstance = hInstance;
	if (FAILED(DirectInput8Create(m_hInstance,
		DIRECTINPUT_VERSION,IID_IDirectInput8,(void**)&m_pInput,NULL)))
	{
		LOG::Instance()->OutputError("DirectInput8Create Failed");
		return false;
	}

	if (FAILED(m_pInput->CreateDevice(GUID_SysKeyboard,&m_pDevKeyBoard,NULL)))
	{
		LOG::Instance()->OutputError("m_pInput->CreateDevice keyboard Failed");
		return false;
	}
	m_pDevKeyBoard->SetDataFormat(&c_dfDIKeyboard);
	m_pDevKeyBoard->SetCooperativeLevel(hWnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	m_pDevKeyBoard->Acquire();

	if (FAILED(m_pInput->CreateDevice(GUID_SysMouse,&m_pDevMouse,NULL)))
	{
		LOG::Instance()->OutputError("m_pInput->CreateDevice mouse Failed");
		return false;
	}
	m_pDevMouse->SetDataFormat(&c_dfDIMouse);
	m_pDevMouse->SetCooperativeLevel(hWnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	m_pDevMouse->Acquire();
	LOG::Instance()->OutputSuccess("Input Devices Initiation Successful");
	return true;
}

void CInput::Clearup()
{
	if (m_pDevKeyBoard != NULL)
	{
		m_pDevKeyBoard->Release();
	}
	if (m_pDevMouse != NULL)
	{
		m_pDevMouse->Release();
	}
	if (m_pInput != NULL)
	{
		m_pInput->Release();
	}
}

void CInput::Update()
{
	HRESULT hr;
	while (true)
	{
		if (SUCCEEDED(hr = m_pDevKeyBoard->GetDeviceState(256,(void*)&m_keyState)))
		{
			break;
		}

		if (hr != DIERR_INPUTLOST && hr != DIERR_NOTACQUIRED)
		{
			return;
		}

		if (FAILED(m_pDevKeyBoard->Acquire()))
		{
			return;
		}
	}

	while (true)
	{
		if (SUCCEEDED(hr = m_pDevMouse->GetDeviceState(sizeof(DIMOUSESTATE),(void*)&m_mouseState)))
		{
			break;
		}

		if (hr != DIERR_INPUTLOST && hr != DIERR_NOTACQUIRED)
		{
			return;
		}

		if (FAILED(m_pDevMouse->Acquire()))
		{
			return;
		}
	}
}

bool CInput::IsKeyDown( DWORD dwKeyCode,bool bIgnoreStamp )
{
	if ((m_keyState[dwKeyCode] & 0x80) != 0x80)
	{
		return false;
	}

	if (bIgnoreStamp)
	{
		return true;
	}
	else
	{
		if (TIMER.GetGameTime() - m_nKeyStamp[dwKeyCode] >= 500)
		{
			m_nKeyStamp[dwKeyCode] = TIMER.GetGameTime();
			return true;
		}
		else
		{
			return false;
		}
	}	
}

bool CInput::IsMouseButtonDown( DWORD dwButton,bool bIgnoreStamp )
{
	if ((m_mouseState.rgbButtons[dwButton] & 0x80) != 0x80)
	{
		return false;
	}

	if (bIgnoreStamp)
	{
		return true;
	}
	else
	{
		if (TIMER.GetGameTime() - m_nMouseStamp[dwButton] >= 300)
		{
			m_nMouseStamp[dwButton] = TIMER.GetGameTime();
			return true;
		}
		else
		{
			return false;
		}
	}
}

long CInput::GetDeltaX()
{
	return m_mouseState.lX;
}

long CInput::GetDeltaY()
{
	return m_mouseState.lY;
}

long CInput::GetDeltaWheel()
{
	return m_mouseState.lZ;
}

long CInput::GetMousePosX()
{
	POINT pt;
	::GetCursorPos(&pt);
	::ScreenToClient(m_hWnd,&pt);
	return pt.x;
}

long CInput::GetMousePosY()
{
	POINT pt;
	::GetCursorPos(&pt);
	::ScreenToClient(m_hWnd,&pt);
	return pt.y;
}